/**
 * 
 */
package com.magnusart.scrumify.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.magnusart.scrumppm.model.Project;
import com.magnusart.scrumppm.model.ProjectBuilder;

/**
 * @author magnus
 * 
 */
final public class HsqlDbProjectDAO3 implements ProjectDAO3
{

	/**
	 * Describes different modes of fetching data from the database.
	 * @author Magnus Andersson
	 *
	 */
	private static enum Modes{
		IS_DONE, IS_NOT_DONE, DO_NOT_CARE;
	}
	
	/**
	 * This factory instance is used to execute queries
	 */
	private HsqlDbDAOFactory factory;
	
	/**
	 * Place holder for SQL-commands
	 */
	private String sql;
	
	/**
	 * Only allowed to create instances from within this package (by the factory
	 * methods)
	 */
	protected HsqlDbProjectDAO3( HsqlDbDAOFactory factory ) {
		this.factory = factory;
	}

	@Override
	public Project addNewProject( Project project ) {
		
		String name = project.getName();
		String description = project.getDescription();
		
		//TODO Add prepared statement
		sql = "INSERT INTO Projects( projectName, description ) " +
					"VALUES( '" + name + "', '" + description + "' )";
		
		try {
			// Execute the SQL Query
			int i = factory.executeUpdate( sql );

			if ( i == -1 )
				return null;

		} catch ( SQLException e ) {
			return null;
		}


		return project;
	}

	@Override
	public List<Project> getAllProjects() {
		return getProjects( Modes.DO_NOT_CARE );
	}

	@Override
	public List<Project> getOpenProjects() {
		return getProjects( Modes.IS_NOT_DONE );
	}
	
	@Override
	public List<Project> getClosedProjects() {
		return getProjects( Modes.IS_DONE );
	}

	private List<Project> getProjects( Modes mode ) {
		
		List<Project> projects = new ArrayList<Project>();
		ResultSet rs;

		switch( mode ) {
			case IS_DONE:
				sql = "SELECT projectName, description, isDone FROM Projects WHERE isDone = TRUE";
				break;
			case IS_NOT_DONE:
				sql = "SELECT projectName, description, isDone FROM Projects WHERE isDone = FALSE";
				break;
			case DO_NOT_CARE:
				sql = "SELECT projectName, description, isDone FROM Projects";
				break;
			default:
				return null;
		}
		
		
		try {
			rs = factory.executeQuery( sql );

			// Get all the projects and put them in a Map (sorted).
			while ( rs.next() ) {
				
				ProjectBuilder builder = new ProjectBuilder();
				builder.setName( rs.getString( "projectName" ) );
				builder.setDescription( rs.getString( "description" ) );
				builder.setDone( rs.getBoolean( "isDone" )  );
				// Populate a new Project instance.
				Project p = new Project( builder );
				
				projects.add( p	);
				
			}

		} catch ( SQLException e ) {
			System.err.println("Could not retrieve projects.");
		}

		// Sort this list before returning it.
		Collections.sort( projects );
		
		return projects;	
	}
	
	@Override
	public Project closeProject( Project project ) {
		if( setProjectStatusProject( project, true ) ) {
			return getChangeProjectStatus( project );
		} else {
			return null;
		}
	}
	
	@Override
	public Project openProject( Project project ) {
		if( setProjectStatusProject( project, false ) ) {
			return getChangeProjectStatus( project );
		} else {
			return null;
		}
	}
	
	private Project getChangeProjectStatus( Project project ) {
		ProjectBuilder builder = new ProjectBuilder( project );
		builder.setDone( !project.isDone() );
		return new Project( builder );
	}
	
	private boolean setProjectStatusProject( Project project, boolean isDone ) {
		sql = "UPDATE Projects SET isDone = "+ isDone +" WHERE projectName = '" + project.getName() + "'";
		
		try {
			int i = factory.executeUpdate( sql );
			
			if( i == -1 )
				return false;
			
		} catch ( SQLException e ) {
			System.err.println("Failed to close project " + project.getName() + ".");
		}
		
		return true;
	}

	@Override
	public Project deleteProject( Project project ) {
		sql = "DELETE FROM Projects WHERE projectName = '" + project.getName() + "'";
		
		try {
			int i = factory.executeUpdate( sql );
			
			if( i == -1 )
				return null;
			
		} catch ( SQLException e ) {
			e.printStackTrace();
			System.err.println("Failed to delete project " + project.getName() + ".");
		}
		
		return project;
	}
}
